package ms.unicorn.reasoning;

import java.util.BitSet;
import java.util.HashSet;
import java.util.Set;

public class AnnotatedAlternative extends HashSet<FDNode> implements Comparable<AnnotatedAlternative> {
	private static final long serialVersionUID = 1L;
	//private final Set<FDNode> alternatives;
	float mb = 0;
	float rr = 0;
	String evolutionPath = "";
	
	public AnnotatedAlternative() {
		//alternatives = new HashSet<FDNode>();
		
	}
	
	public AnnotatedAlternative(int cap) {
		super(cap);
	}
	
	public AnnotatedAlternative(Set<FDNode> nodes, float mb, float rr, String possibility) {
		super(nodes);
		//alternatives = new HashSet<FDNode>(nodes);
		//this.addAll(nodes);
		this.mb = mb;
		this.rr = rr;
		this.evolutionPath = possibility;
	}
	
	public AnnotatedAlternative(FDNode node, float mb, float rr) {
		//alternatives = new HashSet<FDNode>();
		//alternatives.add(node);
		this.add(node);
		this.mb = mb;
		this.rr = rr;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append('{');
		int i = 0;
		for (FDNode child: this) {
			if (i > 0) builder.append(',');
			builder.append(child.getName());
			i++;
		}
		builder.append('}');
		/*builder.append(mb);
		builder.append(',');
		builder.append(rr);
		builder.append(',');
		builder.append(evolutionPath);*/
		return builder.toString();
	}
	
	public float getMaxBelief() {
		return mb;
	}

	public void setMaxBelief(float mb) {
		this.mb = mb;
	}

	public float getDeferalBelief() {
		return rr;
	}

	public void setRR(float rr) {
		this.rr = rr;
	}

	
	public String getEvolutionPath() {
		return this.evolutionPath;
	}
	
	public void setEvolutionPath(String possibility) {
		this.evolutionPath = possibility;
	}
	
	
	@Override
	public boolean contains(Object o) {
		boolean result = super.contains(o);
		if (!result) {
			//TODO: implement compare component by name feature
			BitSet s;
			
		}
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof AnnotatedAlternative) {
			AnnotatedAlternative o = (AnnotatedAlternative) obj;
			return o.evolutionPath.equals(this.evolutionPath) && super.equals(o);
		}
		return super.equals(obj);
	}
	
	public boolean equals(AnnotatedAlternative o, boolean checkEvolutionPath) {
		return (checkEvolutionPath ? o.evolutionPath.equals(this.evolutionPath) : true) && super.equals(o);
	}
	
	
	@Override
	public int compareTo(AnnotatedAlternative o) {
		/*boolean le = o.alternatives.containsAll(alternatives);
		boolean ge = alternatives.containsAll(o.alternatives);*/
		if (!evolutionPath.equals(o.evolutionPath)) return 2;
		boolean le = o.containsAll(this);
		boolean ge = containsAll(o);
		if (le)
			if (ge) return 0; else return -1;
		else if (ge) return 1;
		else return 2;
	}
	
	
	public boolean isGreaterEqual(AnnotatedAlternative o, boolean checkEvolutionPath) {
		return (checkEvolutionPath ? evolutionPath.equals(o.evolutionPath) : true) && containsAll(o);
	}

	public static AnnotatedAlternative join(AnnotatedAlternative a, AnnotatedAlternative b) {
		AnnotatedAlternative c = new AnnotatedAlternative(a.size()*b.size());
		c.addAll(a);
		c.addAll(b);
		c.mb = a.mb * b.mb;
		c.rr = 1 - (1 - a.rr) * (1 - b.rr);
		c.evolutionPath = a.evolutionPath + b.evolutionPath;
		return c;
	}
}